classdef RotationSignalModel < matlab.System
    % 旋转信号模型: 基于俯仰角和方位角, 计算旋转对接收信号载波功率和相位(包括近似相位和准确的模型相位)
    % 注意: 载波功率和相位的更新频率应与运动模型不同
    
    properties(Nontunable)
        config              % 信号生成配置
        antennaParams       % 天线参数（h/W/Le）
        updateTime          % 更新时间间隔  (s)
        IF_carrierFreq      % 中频载波频率(Hz)
        R                   % 旋转半径(m)
        rotPhaseToZero      % 忽略旋转相位调制
        rotAmpToZero        % 忽略旋转幅度调制
        ampScale            % 归一化旋转幅度
    end

    properties(Access = private)
        carrierWavelength   % 载波波长(m)
        prevTime            % 上一段数据的结束时间
    end

    methods(Access = public)
        function obj = RotationSignalModel(config, ~)
            % 初始化：加载参数+简化卫星初始位置
            obj.config = config;
            obj.IF_carrierFreq = config.signal.CenterFrequency;
            obj.carrierWavelength = config.signal.carrierWavelength;
            obj.R = config.rotation.radius;
            
            % 1. 天线方向图参数（复用config配置）
            obj.antennaParams.h = config.antennaPattern.h;
            obj.antennaParams.W = config.antennaPattern.W;
            obj.antennaParams.Le = config.antennaPattern.Le;
            
            % 3. 流处理核心参数
            % obj.updateTime    = receiverConfig.tracker.totalIntegTime;
            obj.updateTime = config.motion.motionUpdateTime; % (暂时修改，仅为测试)

            % 4. 旋转模型参数
            obj.rotPhaseToZero = config.rotation.rotPhaseToZero; % 忽略旋转相位调制
            obj.rotAmpToZero = config.rotation.rotAmpToZero; % 忽略旋转幅度调制
            obj.ampScale = config.rotation.ampScale; % 归一化旋转幅度
        end
    end

    methods(Access = protected)

        function [pattern, Etheta, Ephi] = calcAntennaPattern(obj, theta, phi)
            % 计算贴片天线的方向图
            % 输出：方向图、Etheta、Ephi
            
            h = obj.antennaParams.h;
            W = obj.antennaParams.W;
            Le = obj.antennaParams.Le;
            lambda = obj.carrierWavelength;
            beta = 2 * pi / lambda; 
            
            sinTheta = sin(theta);
            cosTheta = cos(theta);
            cosPhi = cos(phi);
            sinPhi = sin(phi);
            
            % --- 关键修正：MATLAB sinc 陷阱 ---
            % 公式中的 sinc(x) 对应 MATLAB 的 sinc(x/pi)
            
            % 计算 Sinc 函数的参数 (Argument)
            arg_h = (beta * h / 2) * sinTheta .* cosPhi;
            arg_W = (beta * W / 2) * sinTheta .* sinPhi;
            
            % 计算 Cosine (Array Factor) 的参数 - Cosine 不受 sinc 定义影响，保持原样
            arg_Le_theta = (beta * Le / 2) * sinTheta .* cosPhi;
            %arg_Le_phi   = (beta * Le / 2) * sinTheta .* sinPhi;
            
            % Etheta
            % 注意：sinc 的输入除以 pi 后，需要乘以 pi 恢复原始值
            term_sinc_h =  sinc(arg_h / pi); 
            term_sinc_W =  sinc(arg_W / pi);
            
            Etheta = cosPhi .* term_sinc_h ...
                            .* term_sinc_W ...
                            .* cos(arg_Le_theta);
            
            % Ephi
            Ephi = cosTheta .* sinPhi .* term_sinc_h ...
                            .* term_sinc_W ...
                            .* cos(arg_Le_theta);
            
            pattern = abs(Etheta).^2 + abs(Ephi).^2;
        end

        function setupImpl(obj)
            % 初始化参数验证
            if obj.IF_carrierFreq < 0
                error('中频载波频率必须为非负数');
            end
        end

        function signalSeg = stepImpl(obj, motionDataSeg)
            %  旋转信号模型: 基于俯仰角和方位角, 计算旋转对接收信号载波功率和相位(包括近似相位和准确的模型相位)
            % 输出: signalSeg - 单段信号数据结构体
            % - time: 单段时间
            % - powerRot: 贴片天线的方向图
            % - phaseRot: 接收信号的载波相位

            signalSeg.time = motionDataSeg.time;
    
            %% 接收功率（天线方向图）
            % 忽略旋转幅度调制
            if obj.rotAmpToZero
                signalSeg.powerRot = ones(size(motionDataSeg.cosThetaM));
            else
                [signalSeg.powerRot, signalSeg.Etheta, signalSeg.Ephi] = obj.calcAntennaPattern(motionDataSeg.thetaM, motionDataSeg.phiM);

            end
                    
            %% 准确载波相位（无近似，基于参考距离的真实几何）

            % Note: phi0_t这一部分已经在SignalModulator.m中计算过了，因此不用表示
            % phi0_t = 2 * pi * obj.IF_carrierFreq * signalSeg.time; 
            % eps_m: 这一部分表示各天线上相对独立的载波相位成分，通过PLL/FLL估计
            % eps_m = obj.config.antennas.phaseOffsets.';
            % 忽略旋转相位调制
            if obj.rotPhaseToZero
                signalSeg.phaseRot = zeros(size(motionDataSeg.cosThetaM));
            else
                signalSeg.phaseRot = 2* pi * motionDataSeg.cosThetaM * obj.R/ obj.carrierWavelength;
            end
            % 相位wrap到(-π, π)
            signalSeg.phaseRot = wrapToPi(signalSeg.phaseRot);
            % signalSeg.power = signalSeg.power / max(signalSeg.power(:));
            obj.prevTime = signalSeg.time(end);
        end

        function resetImpl(obj)
            obj.prevTime = 0;
        end
    end
end